# -*- coding:utf-8 -*-

import socketserver
import Survey.Socket
import traceback
from twisted.internet import protocol,reactor
from time import ctime
import json

HOST = '192.168.0.200'
PORT = 21567
BUFSIZE = 20000
ADDR = (HOST,PORT)

connectMap = {}

number = 0

import resource
resource.setrlimit(resource.RLIMIT_NOFILE, (2000, 2000))

class TcpServerHandler(protocol.Protocol):

    def __init__(self):
        self.id = 0

        self.handlerMap = {
            "ping":self.on_ping,
            "info":self.on_info,
            "send":self.on_send,
            "close":self.on_close
        }

        self.sendData = []

        pass

    def connectionMade(self):
        self.clnt = self.transport.getPeer().host

        # global number
        # number+=1
        # self.id = number
        print(" ...connect from :",self.clnt)

    def connectionLost(self, reason):
        print("connect lost reason {} id {}".format(reason,self.id))
        print(self.transport.disconned)
        # global connectMap
        # del connectMap[self.id]

    def makeConnection(self, transport):
        super(TcpServerHandler, self).makeConnection(transport)

    def dataReceived(self, data):
        print("id: {}<< {}".format(self.id,data))
        try:
            rString = data.decode('utf-8')
            if rString is not None and len(rString) > 0:
                obj = json.loads(rString)
                if self.handle_msg(obj) == False:
                    pass
                else:
                    pass
                self.final_send()
            else:
                return
        except Exception as e:
            print(e)
            traceback.print_last()
            return


    def send(self, string):
        print(">> ",string)
        self.sendData.append(string)

        # self.transport.write(string.encode('utf-8'))



    def final_send(self):
        if len(self.sendData) == 0:
            return
        jsonString = json.dumps(self.sendData)
        self.transport.write(jsonString.encode("utf-8"))
        self.sendData = []

    def send_json(self,obj):
        string = json.dumps(obj)
        self.send(string)

    def send_pong(self):
        pong = {'cmd':"pong"}
        self.send_json(pong)

    def send_close(self):
        cmd = {'cmd':"close"}
        self.send_json(cmd)

    def save_client(self,info):
        id = info['id']
        self.id = id
        global connectMap
        self.transport.clientId = id
        connectMap[id] = self


    def send_to_client(self,id,obj):
        string = json.dumps(obj)
        global connectMap
        if id not in connectMap:
            return False
        client = connectMap[id]
        msg = {
            "cmd":"msg",
            "content":"this is content"
        }

        if client.connected == 1:
            client.send_json(msg)
        else:
            return False
        # client.write(string.encode('utf-8'))
        # self.send_ok()

    def send_ok(self):
        cmd = {"cmd":"ok"}
        self.send_json(cmd)


    def on_ping(self,obj):
        pong = {'cmd': "pong"}
        self.send_json(pong)

    def on_error(self,obj):
        error = {'cmd':"error"}
        self.send_json(error)

    def on_info(self,obj):
        self.save_client(obj)
        self.send_ok()

    def on_close(self,obj):
        cmd = {'cmd': "close"}
        self.send_json(cmd)

    def on_send(self,obj):
        id = obj["id"]
        self.send_to_client(id,obj)
        pass

    def handle_msg(self,obj):
        cmd = obj['cmd']
        if cmd not in self.handlerMap:
            self.on_error()

        handler = self.handlerMap[cmd]
        ret =  handler(obj)
        return ret


    @classmethod
    def run(self):
        factory = protocol.Factory()
        factory.protocol = TcpServerHandler
        print("waiting for connection ...")
        reactor.listenTCP(PORT,factory)
        reactor.run()






# class Server:
#
#     def __init__(self):
#
#         self.tcpServer  = None
#         self.clientMap = {}
#         pass
#
#
#     def start(self):
#         self.tcpServer = socket(AF_INET,SOCK_STREAM)
#         self.tcpServer.bind(ADDR)
#         self.tcpServer.listen(5)
#
#         while True:
#             print("waiting for connection....")
#             client , adr = self.tcpServer.accept()
#             while True:
#                 try:
#                     data = client.recv(BUFSIZE)
#                     rString = data.decode('utf-8')
#                     print("<< ",rString)
#                     if rString is not None and len(rString) > 0:
#                         obj = json.loads(rString)
#                         if self.handle(client,obj) == False:
#                             break
#                     else:
#                         client.close()
#                         break
#                 except Exception as e:
#                     print(e)
#                     break
#
#
#
#
#
#
#     def send(self,client,string):
#         client.send(string.encode('utf-8'))
#
#     def send_json(self,client,obj):
#         string = json.dumps(obj)
#         self.send(client,string)
#
#     def send_pong(self,client):
#         pong = {'cmd':"pong"}
#         self.send_json(client,pong)
#
#     def send_close(self,client):
#         cmd = {'cmd':"close"}
#         self.send_json(client,cmd)
#
#     def save_client(self,client,info):
#         id = info['id']
#         self.clientMap[id] = client
#
#     def send_ok(self,client):
#         cmd = {"cmd":"ok"}
#         self.send_json(client,cmd)
#
#     def handle(self,client,obj):
#         cmd = obj['cmd']
#         if cmd == 'info':
#             self.save_client(client,obj)
#             self.send_ok(client)
#
#         if cmd == 'ping':
#             self.send_pong(client)
#
#         if cmd == 'close':
#             self.send_close(client)
#             client.close()
#             return False
#
#         if cmd == '':
#             client.close()
#             return False
#
#         return True
#
#
#     def close(self):
#         self.tcpServer.close()